package com.harmontronics.hanma.paas.paas.domain.app.service.tools;

import cn.hutool.core.collection.CollectionUtil;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.harmontronics.hanma.paas.paas.utils.ConvertUtil;
import com.harmontronics.hanma.paas.paas.utils.StringUtil;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import lombok.extern.slf4j.Slf4j;

/**
 * @Title: 表单/记录字段显示内容解析器
 * @ClassName: FieldDisplayRuleParser
 * @Description: 对于关联业务模型的数据字段，有时会关联模型中的多个字段，
 * <br/>并按照自定义的规则生成期望的字符串，用以显示，规则如：[${device_code}]${device_name}
 * @Author: tylr
 * @Date: 2021/6/3 10:05
 * @Version: 1.0.0
 */
@Slf4j
public class FieldDisplayRuleParser {

    /**
     * 关联字段规则解析正则
     */
    private static final Pattern RELATION_COLUMN_PARSE_PATTERN = Pattern.compile("(\\$\\s*\\{([a-z0-9_\\s]+)\\})");

    /**
     * 错误处理
     */
    private final static String ERROR_NULL = "NULL";

    /****************************** 临时缓存 ******************************/
    /**
     * 关联业务模型的数据字段显示规则解析缓存
     * <p><显示规则字符串,解析规则><p/>
     */
    private static Map<String, FieldDisplayRuleBO> fieldDisplayRuleCache = Maps.newConcurrentMap();

    public static FieldDisplayRuleBO getFieldDisplayRuleResult(String displayRule){
        if(fieldDisplayRuleCache.containsKey(displayRule)){
            return fieldDisplayRuleCache.get(displayRule);
        }
        FieldDisplayRuleBO fieldDisplayRule = new FieldDisplayRuleBO(displayRule);
        FieldDisplayRuleParser.parseFieldDisplayRule(fieldDisplayRule);
        // 临时缓存
        fieldDisplayRuleCache.put(displayRule,fieldDisplayRule);
        return fieldDisplayRule;
    }

    /****************************** 临时缓存 ******************************/

    public static void parseFieldDisplayRule(FieldDisplayRuleBO fieldDisplayRule){
        if(fieldDisplayRule!=null &&
                StringUtil.isNotBlank(fieldDisplayRule.getDisplayRule())){
            List<String> relatedModelColumnCodes = new ArrayList<>();
            // 去除 displayRule 头尾的空格
            String displayRule = StringUtil.strip(fieldDisplayRule.getDisplayRule());
            Matcher matcher = RELATION_COLUMN_PARSE_PATTERN.matcher(displayRule);
            String displayRuleFormat = displayRule;
            while (matcher.find()) {
                String relatedModelColumnCodeRule = matcher.group(1);
                String relatedModelColumnCode = matcher.group(2);
                relatedModelColumnCodes.add(relatedModelColumnCode);
                displayRuleFormat = displayRuleFormat.replace(relatedModelColumnCodeRule,"%s");
            }
            fieldDisplayRule.setRelationColumns(relatedModelColumnCodes);
            fieldDisplayRule.setFieldDisplayFormat(displayRuleFormat);
        }
    }

    public static String getRelationColumnDisplayValue(Map<String, Object> values, FieldDisplayRuleBO fieldDisplayRule) {
        if(CollectionUtil.isNotEmpty(fieldDisplayRule.getRelationColumns())
        && StringUtil.isNotBlank(fieldDisplayRule.getFieldDisplayFormat())){
            List<String> realValues = Lists.newArrayList();
            fieldDisplayRule.getRelationColumns().forEach(it->{
                String dataValue = ConvertUtil.getValueFromMap(values,it,String.class);
                if(StringUtil.isBlank(dataValue)){
                    realValues.add(ERROR_NULL);
                }else{
                    realValues.add(dataValue);
                }
            });
            // 将 displayRule 中的${columnCode}用%s替换
            return String.format(fieldDisplayRule.getFieldDisplayFormat(), realValues.toArray());
        }
        return null;
    }

    /**
     *
     * @param values
     * @param displayRule
     * @return
     */
    public static String getRelationColumnDisplayValue(Map<String, Object> values, String displayRule) {
        if(StringUtil.isBlank(displayRule) || values== null || values.isEmpty()){
            return null;
        }

        // 从显示规则中抽取出关联字段的 columnCode
        FieldDisplayRuleBO fieldDisplayRule = new FieldDisplayRuleBO(displayRule);
        parseFieldDisplayRule(fieldDisplayRule);

        return getRelationColumnDisplayValue(values,fieldDisplayRule);
    }

    private static void relationColumnRuleParseTest(String displayRule) {
        displayRule = StringUtil.strip(displayRule);
        Map<String, Object> item = Maps.newHashMap();
        item.put("id",1);
        item.put("device_code","10001");
        item.put("device_name","注塑机");

        String label = getRelationColumnDisplayValue(item,displayRule);
        System.out.println(label);
    }

    public static void main(String[] args) {
        Map<String, Object> item = Maps.newHashMap();
        item.put("id",1);
        item.put("device_code","10001");
        item.put("device_name","注塑机");

        System.out.println(getRelationColumnDisplayValue(item,"[${ device_code }]${ device_name }"));
        System.out.println(getRelationColumnDisplayValue(item,"[${device_code}]${device_name}"));
        System.out.println(getRelationColumnDisplayValue(item,"{${device_code}}_${device_name}"));
        System.out.println(getRelationColumnDisplayValue(item,"{${device_code}}_$$${device_name}"));
        System.out.println(getRelationColumnDisplayValue(item,"${device_code}"));
        System.out.println(getRelationColumnDisplayValue(item,"$  {device_code} "));
    }
}
